---
title: Wasm Plugin
description: Extend the functionality provided by the Istio proxy through WebAssembly filters.
location: https://istio.io/docs/reference/config/proxy_extensions/wasm-plugin.html
layout: protoc-gen-docs
generator: protoc-gen-docs
schema: istio.extensions.v1alpha1.WasmPlugin
aliases: [/docs/reference/config/extensions/v1alpha1/wasm-plugin]
number_of_entries: 8
---
<p>WasmPlugins provides a mechanism to extend the functionality provided by
the Istio proxy through WebAssembly filters.</p>
<p>Order of execution (as part of Envoy&rsquo;s filter chain) is determined by
phase and priority settings, allowing the configuration of complex
interactions between user-supplied WasmPlugins and Istio&rsquo;s internal
filters.</p>
<p>Examples:</p>
<p>AuthN Filter deployed to ingress-gateway that implements an OpenID flow
and populates the <code>Authorization</code> header with a JWT to be consumed by
Istio AuthN.</p>
<pre><code class="language-yaml">apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
  name: openid-connect
  namespace: istio-ingress
spec:
  selector:
    matchLabels:
      istio: ingressgateway
  url: file:///opt/filters/openid.wasm
  sha256: 1ef0c9a92b0420cf25f7fe5d481b231464bc88f486ca3b9c83ed5cc21d2f6210
  phase: AUTHN
  pluginConfig:
    openid_server: authn
    openid_realm: ingress
</code></pre>
<p>This is the same as the last example, but using an OCI image.</p>
<pre><code class="language-yaml">apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
  name: openid-connect
  namespace: istio-ingress
spec:
  selector:
    matchLabels:
      istio: ingressgateway
  url: oci://private-registry:5000/openid-connect/openid:latest
  imagePullPolicy: IfNotPresent
  imagePullSecret: private-registry-pull-secret
  phase: AUTHN
  pluginConfig:
    openid_server: authn
    openid_realm: ingress
</code></pre>
<p>This is the same as the last example, but using VmConfig to configure environment variables in the VM.</p>
<pre><code class="language-yaml">apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
  name: openid-connect
  namespace: istio-ingress
spec:
  selector:
    matchLabels:
      istio: ingressgateway
  url: oci://private-registry:5000/openid-connect/openid:latest
  imagePullPolicy: IfNotPresent
  imagePullSecret: private-registry-pull-secret
  phase: AUTHN
  pluginConfig:
    openid_server: authn
    openid_realm: ingress
  vmConfig:
    env:
    - name: POD_NAME
      valueFrom: HOST
    - name: TRUST_DOMAIN
      value: &quot;cluster.local&quot;
</code></pre>
<p>This is also the same as the last example, but the Wasm module is pulled via https and updated for each time when this plugin resource is changed.</p>
<pre><code class="language-yaml">apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
  name: openid-connect
  namespace: istio-ingress
spec:
  selector:
    matchLabels:
      istio: ingressgateway
  url: https://private-bucket/filters/openid.wasm
  imagePullPolicy: Always
  phase: AUTHN
  pluginConfig:
    openid_server: authn
    openid_realm: ingress
  vmConfig:
    env:
    - name: POD_NAME
      valueFrom: HOST
    - name: TRUST_DOMAIN
      value: &quot;cluster.local&quot;
</code></pre>
<p>And a more complex example that deploys three WasmPlugins and orders them
using <code>phase</code> and <code>priority</code>. The (hypothetical) setup is that the
<code>openid-connect</code> filter performs an OpenID Connect flow to authenticate the
user, writing a signed JWT into the Authorization header of the request,
which can be verified by the Istio authn plugin. Then, the <code>acl-check</code> plugin
kicks in, passing the JWT to a policy server, which in turn responds with a
signed token that contains information about which files and functions of the
system are available to the user that was previously authenticated. The
<code>acl-check</code> filter writes this token to a header. Finally, the <code>check-header</code>
filter verifies the token in that header and makes sure that the token&rsquo;s
contents (the permitted &lsquo;function&rsquo;) matches its plugin configuration.</p>
<p>The resulting filter chain looks like this:
-&gt; openid-connect -&gt; istio.authn -&gt; acl-check -&gt; check-header -&gt; router</p>
<pre><code class="language-yaml">apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
  name: openid-connect
  namespace: istio-ingress
spec:
  selector:
    matchLabels:
      istio: ingressgateway
  url: oci://private-registry:5000/openid-connect/openid:latest
  imagePullPolicy: IfNotPresent
  imagePullSecret: private-registry-pull-secret
  phase: AUTHN
  pluginConfig:
    openid_server: authn
    openid_realm: ingress
</code></pre>
<pre><code class="language-yaml">apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
  name: acl-check
  namespace: istio-ingress
spec:
  selector:
    matchLabels:
      istio: ingressgateway
  url: oci://private-registry:5000/acl-check/acl:latest
  imagePullPolicy: Always
  imagePullSecret: private-registry-pull-secret
  phase: AUTHZ
  priority: 1000
  pluginConfig:
    acl_server: some_server
    set_header: authz_complete
</code></pre>
<pre><code class="language-yaml">apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
  name: check-header
  namespace: istio-ingress
spec:
  selector:
    matchLabels:
      istio: ingressgateway
  url: oci://private-registry:5000/check-header:latest
  imagePullPolicy: IfNotPresent
  imagePullSecret: private-registry-pull-secret
  phase: AUTHZ
  priority: 10
  pluginConfig:
    read_header: authz_complete
    verification_key: a89gAzxvls0JKAKIJSBnnvvvkIO
    function: read_data
</code></pre>

<h2 id="WasmPlugin">WasmPlugin</h2>
<section>
<p>WasmPlugins provides a mechanism to extend the functionality provided by
the Istio proxy through WebAssembly filters.</p>

<table class="message-fields">
<thead>
<tr>
<th>Field</th>
<th>Type</th>
<th>Description</th>
<th>Required</th>
</tr>
</thead>
<tbody>
<tr id="WasmPlugin-selector">
<td><code>selector</code></td>
<td><code><a href="https://istio.io/docs/reference/config/type/workload-selector.html#WorkloadSelector">WorkloadSelector</a></code></td>
<td>
<p>Criteria used to select the specific set of pods/VMs on which
this plugin configuration should be applied. If omitted, this
configuration will be applied to all workload instances in the same
namespace. If the <code>WasmPlugin</code> is present in the config root
namespace, it will be applied to all applicable workloads in any
namespace.</p>

</td>
<td>
No
</td>
</tr>
<tr id="WasmPlugin-url">
<td><code>url</code></td>
<td><code>string</code></td>
<td>
<p>URL of a Wasm module or OCI container. If no scheme is present,
defaults to <code>oci://</code>, referencing an OCI image. Other valid schemes
are <code>file://</code> for referencing .wasm module files present locally
within the proxy container, and <code>http[s]://</code> for .wasm module files
hosted remotely.</p>

</td>
<td>
No
</td>
</tr>
<tr id="WasmPlugin-sha256">
<td><code>sha256</code></td>
<td><code>string</code></td>
<td>
<p>SHA256 checksum that will be used to verify Wasm module or OCI container.
If the <code>url</code> field already references a SHA256 (using the <code>@sha256:</code>
notation), it must match the value of this field. If an OCI image is
referenced by tag and this field is set, its checksum will be verified
against the contents of this field after pulling.</p>

</td>
<td>
No
</td>
</tr>
<tr id="WasmPlugin-image_pull_policy">
<td><code>imagePullPolicy</code></td>
<td><code><a href="#PullPolicy">PullPolicy</a></code></td>
<td>
<p>The pull behaviour to be applied when fetching Wasm module by either
OCI image or http/https. Only relevant when referencing Wasm module without
any digest, including the digest in OCI image URL or sha256 field in <code>vm_config</code>.
Defaults to IfNotPresent, except when an OCI image is referenced in the <code>url</code>
and the <code>latest</code> tag is used, in which case <code>Always</code> is the default,
mirroring K8s behaviour.</p>

</td>
<td>
No
</td>
</tr>
<tr id="WasmPlugin-image_pull_secret">
<td><code>imagePullSecret</code></td>
<td><code>string</code></td>
<td>
<p>Credentials to use for OCI image pulling.
Name of a K8s Secret in the same namespace as the <code>WasmPlugin</code> that
contains a docker pull secret which is to be used to authenticate
against the registry when pulling the image.</p>

</td>
<td>
No
</td>
</tr>
<tr id="WasmPlugin-plugin_config">
<td><code>pluginConfig</code></td>
<td><code><a href="https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#struct">Struct</a></code></td>
<td>
<p>The configuration that will be passed on to the plugin.</p>

</td>
<td>
No
</td>
</tr>
<tr id="WasmPlugin-plugin_name">
<td><code>pluginName</code></td>
<td><code>string</code></td>
<td>
<p>The plugin name to be used in the Envoy configuration (used to be called
<code>rootID</code>). Some .wasm modules might require this value to select the Wasm
plugin to execute.</p>

</td>
<td>
No
</td>
</tr>
<tr id="WasmPlugin-phase">
<td><code>phase</code></td>
<td><code><a href="#PluginPhase">PluginPhase</a></code></td>
<td>
<p>Determines where in the filter chain this <code>WasmPlugin</code> is to be injected.</p>

</td>
<td>
No
</td>
</tr>
<tr id="WasmPlugin-priority">
<td><code>priority</code></td>
<td><code><a href="https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#int32value">Int32Value</a></code></td>
<td>
<p>Determines ordering of <code>WasmPlugins</code> in the same <code>phase</code>.
When multiple <code>WasmPlugins</code> are applied to the same workload in the
same <code>phase</code>, they will be applied by priority, in descending order.
If <code>priority</code> is not set, or two <code>WasmPlugins</code> exist with the same
value, the ordering will be deterministically derived from name and
namespace of the <code>WasmPlugins</code>. Defaults to <code>0</code>.</p>

</td>
<td>
No
</td>
</tr>
<tr id="WasmPlugin-fail_strategy">
<td><code>failStrategy</code></td>
<td><code><a href="#FailStrategy">FailStrategy</a></code></td>
<td>
<p>Specifies the failure behavior for the plugin due to fatal errors.</p>

</td>
<td>
No
</td>
</tr>
<tr id="WasmPlugin-vm_config">
<td><code>vmConfig</code></td>
<td><code><a href="#VmConfig">VmConfig</a></code></td>
<td>
<p>Configuration for a Wasm VM.
more details can be found <a href="https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/wasm/v3/wasm.proto#extensions-wasm-v3-vmconfig">here</a>.</p>

</td>
<td>
No
</td>
</tr>
<tr id="WasmPlugin-match">
<td><code>match</code></td>
<td><code><a href="#WasmPlugin-TrafficSelector">TrafficSelector[]</a></code></td>
<td>
<p>Specifies the criteria to determine which traffic is passed to WasmPlugin.
If a traffic satisfies any of TrafficSelectors,
the traffic passes the WasmPlugin.</p>

</td>
<td>
No
</td>
</tr>
</tbody>
</table>
</section>
<h2 id="VmConfig">VmConfig</h2>
<section>
<p>Configuration for a Wasm VM.
more details can be found <a href="https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/wasm/v3/wasm.proto#extensions-wasm-v3-vmconfig">here</a>.</p>

<table class="message-fields">
<thead>
<tr>
<th>Field</th>
<th>Type</th>
<th>Description</th>
<th>Required</th>
</tr>
</thead>
<tbody>
<tr id="VmConfig-env">
<td><code>env</code></td>
<td><code><a href="#EnvVar">EnvVar[]</a></code></td>
<td>
<p>Specifies environment variables to be injected to this VM.
Note that if a key does not exist, it will be ignored.</p>

</td>
<td>
No
</td>
</tr>
</tbody>
</table>
</section>
<h2 id="EnvVar">EnvVar</h2>
<section>
<table class="message-fields">
<thead>
<tr>
<th>Field</th>
<th>Type</th>
<th>Description</th>
<th>Required</th>
</tr>
</thead>
<tbody>
<tr id="EnvVar-name">
<td><code>name</code></td>
<td><code>string</code></td>
<td>
<p>Required
Name of the environment variable. Must be a C_IDENTIFIER.</p>

</td>
<td>
No
</td>
</tr>
<tr id="EnvVar-value_from">
<td><code>valueFrom</code></td>
<td><code><a href="#EnvValueSource">EnvValueSource</a></code></td>
<td>
<p>Required
Source for the environment variable&rsquo;s value.</p>

</td>
<td>
No
</td>
</tr>
<tr id="EnvVar-value">
<td><code>value</code></td>
<td><code>string</code></td>
<td>
<p>Value for the environment variable.
Note that if <code>value_from</code> is <code>HOST</code>, it will be ignored.
Defaults to &ldquo;&rdquo;.</p>

</td>
<td>
No
</td>
</tr>
</tbody>
</table>
</section>
<h2 id="WasmPlugin-TrafficSelector">WasmPlugin.TrafficSelector</h2>
<section>
<p>TrafficSelector provides a mechanism to select a specific traffic flow
for which this Wasm Plugin will be enabled.
When all the sub conditions in the TrafficSelector are satisfied, the
traffic will be selected.</p>

<table class="message-fields">
<thead>
<tr>
<th>Field</th>
<th>Type</th>
<th>Description</th>
<th>Required</th>
</tr>
</thead>
<tbody>
<tr id="WasmPlugin-TrafficSelector-mode">
<td><code>mode</code></td>
<td><code><a href="https://istio.io/docs/reference/config/type/workload-selector.html#WorkloadMode">WorkloadMode</a></code></td>
<td>
<p>Criteria for selecting traffic by their direction.
Note that CLIENT and SERVER are analogous to OUTBOUND and INBOUND,
respectively.
For the gateway, the field should be CLIENT or CLIENT_AND_SERVER.
If not specified, the default value is CLIENT_AND_SERVER.</p>

</td>
<td>
No
</td>
</tr>
<tr id="WasmPlugin-TrafficSelector-ports">
<td><code>ports</code></td>
<td><code><a href="https://istio.io/docs/reference/config/type/workload-selector.html#PortSelector">PortSelector[]</a></code></td>
<td>
<p>Criteria for selecting traffic by their destination port.
More specifically, for the outbound traffic, the destination port would be
the port of the target service. On the other hand, for the inbound traffic,
the destination port is the port bound by the server process in the same Pod.</p>
<p>If one of the given <code>ports</code> is matched, this condition is evaluated to true.
If not specified, this condition is evaluated to true for any port.</p>

</td>
<td>
No
</td>
</tr>
</tbody>
</table>
</section>
<h2 id="PluginPhase">PluginPhase</h2>
<section>
<p>The phase in the filter chain where the plugin will be injected.</p>

<table class="enum-values">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr id="PluginPhase-UNSPECIFIED_PHASE">
<td><code>UNSPECIFIED_PHASE</code></td>
<td>
<p>Control plane decides where to insert the plugin. This will generally
be at the end of the filter chain, right before the Router.
Do not specify <code>PluginPhase</code> if the plugin is independent of others.</p>

</td>
</tr>
<tr id="PluginPhase-AUTHN">
<td><code>AUTHN</code></td>
<td>
<p>Insert plugin before Istio authentication filters.</p>

</td>
</tr>
<tr id="PluginPhase-AUTHZ">
<td><code>AUTHZ</code></td>
<td>
<p>Insert plugin before Istio authorization filters and after Istio authentication filters.</p>

</td>
</tr>
<tr id="PluginPhase-STATS">
<td><code>STATS</code></td>
<td>
<p>Insert plugin before Istio stats filters and after Istio authorization filters.</p>

</td>
</tr>
</tbody>
</table>
</section>
<h2 id="PullPolicy">PullPolicy</h2>
<section>
<p>The pull behaviour to be applied when fetching a Wam module,
mirroring K8s behaviour.</p>

<table class="enum-values">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr id="PullPolicy-UNSPECIFIED_POLICY">
<td><code>UNSPECIFIED_POLICY</code></td>
<td>
<p>Defaults to IfNotPresent, except for OCI images with tag <code>latest</code>, for which
the default will be Always.</p>

</td>
</tr>
<tr id="PullPolicy-IfNotPresent">
<td><code>IfNotPresent</code></td>
<td>
<p>If an existing version of the image has been pulled before, that
will be used. If no version of the image is present locally, we
will pull the latest version.</p>

</td>
</tr>
<tr id="PullPolicy-Always">
<td><code>Always</code></td>
<td>
<p>We will always pull the latest version of an image when changing
this plugin. Note that the change includes <code>metadata</code> field as well.</p>

</td>
</tr>
</tbody>
</table>
</section>
<h2 id="EnvValueSource">EnvValueSource</h2>
<section>
<table class="enum-values">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr id="EnvValueSource-INLINE">
<td><code>INLINE</code></td>
<td>
<p>Explicitly given key-value pairs to be injected to this VM</p>

</td>
</tr>
<tr id="EnvValueSource-HOST">
<td><code>HOST</code></td>
<td>
<p><em>Istio-proxy&rsquo;s</em> environment variables exposed to this VM.</p>

</td>
</tr>
</tbody>
</table>
</section>
<h2 id="FailStrategy">FailStrategy</h2>
<section>
<table class="enum-values">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr id="FailStrategy-FAIL_CLOSE">
<td><code>FAIL_CLOSE</code></td>
<td>
<p>A fatal error in the binary fetching or during the plugin execution causes
all subsequent requests to fail with 5xx.</p>

</td>
</tr>
<tr id="FailStrategy-FAIL_OPEN">
<td><code>FAIL_OPEN</code></td>
<td>
<p>Enables the fail open behavior for the Wasm plugin fatal errors to bypass
the plugin execution. A fatal error can be a failure to fetch the remote
binary, an exception, or abort() on the VM. This flag is not recommended
for the authentication or the authorization plugins.</p>

</td>
</tr>
</tbody>
</table>
</section>
